
#include "sc_gui.h"

SC_GUI  *gui;

uint16_t  SC_pfb_buf[SC_PFB_BUF_SIZE];    //内存池2K

//快速运算alpha算法
uint16_t alphaBlend( uint16_t fc, uint16_t bc,uint8_t alpha)
{
    if(alpha>240)  return fc;
    if(alpha<16)   return bc;
    // Split out and blend 5 bit red and blue channels
    uint32_t rxb = bc & 0xF81F;
    rxb += ((fc & 0xF81F) - rxb) * (alpha >> 2) >> 6;
    // Split out and blend 6 bit green channel
    uint32_t xgx = bc & 0x07E0;
    xgx += ((fc & 0x07E0) - xgx) * alpha >> 8;
    // Recombine channels
    return (rxb & 0xF81F) | (xgx & 0x07E0);
}
//初始化系统注册画点函数
void SC_GUI_Init( void (*bsp_pset)(int,int,uint16_t),uint16_t bkc,uint16_t bc,uint16_t fc, void* font)
{
    static SC_GUI tft;
    gui = &tft;
    gui->bkc=bkc;
    gui->bc= bc;
    gui->fc= fc;
    gui->alpha=255;

    gui->dma_i= 0;
    gui->dma_prt= (uint16_t*)SC_pfb_buf;
    gui->pfb_buf= (uint16_t*)SC_pfb_buf;

    gui->lcd_area.xs=0;
    gui->lcd_area.ys=0;
    gui->lcd_area.xe=LCD_SCREEN_WIDTH-1;   //
    gui->lcd_area.ye=LCD_SCREEN_HEIGHT-1;

    gui->font=font;                 //lvgl字库
    gui->bsp_pset = bsp_pset;       //层底画点
    gui->Refresh  = SC_Refresh;
}


/**fun: 矩形填充*/
void SC_pfb_DrawFill(SC_tile *dest,int xs,int ys,int xe,int ye,uint16_t fc)
{
    SC_tile pfb= {0};


__PFB_DrawFill:
    if(dest==NULL||pfb.buf)
    {
        uint16_t colour= (fc==gui->bkc)?gui->bkc:alphaBlend(fc,0,gui->alpha);
        SC_pfb_clip(&pfb,xs,ys,xe,ye,colour);//创建局部pfb
        dest=&pfb;
    }
    else
    {
        //===========计算相交===============
        SC_ARER intersection;
        if(!SC_pfb_intersection(dest,&intersection,xs,ys,xe,ye))
        {
            return;
        }
        for (int y = intersection.ys; y <=intersection.ye; y++)
        {
            int dest_offs=(y-dest->ys) * dest->w -dest->xs;
            for (int x = intersection.xs; x <=intersection.xe; x++)
            {
                dest->buf[dest_offs+x]=alphaBlend(fc,dest->buf[dest_offs+x],gui->alpha);
            }
        }
    }
    if(pfb.buf)
    {
        if( SC_pfb_Refresh(&pfb,0))
        {
            goto __PFB_DrawFill;
        }
    }
}

/**fun: 空芯矩形*/
void SC_pfb_DrawFrame(SC_tile *dest, int xs, int ys, int xe, int ye,uint16_t fc)
{
    SC_pfb_DrawFill(dest, xs, ys, xe, ys,fc);  //上
    SC_pfb_DrawFill(dest, xs, ye, xe, ye,fc);  //下
    SC_pfb_DrawFill(dest, xs, ys+1, xs, ye-1,fc);  //左
    SC_pfb_DrawFill(dest, xe, ys+1, xe, ye-1,fc);  //右
}

///**fun: 清屏*/
void SC_Clear(int xs,int ys,int xe,int ye)
{
    SC_pfb_DrawFill(NULL, xs, ys, xe, ye,gui->bkc);
}

/**fun: 显示图片*/
void SC_pfb_Image(SC_tile *dest,int xs,int ys,SC_img_t *src)
{
    SC_tile pfb= {0};
__PFB_Image:
    if(dest==NULL||pfb.buf)
    {
        //创建局部pfb
        SC_pfb_clip(&pfb,xs,ys,xs+src->w-1,ys+src->h-1,gui->bkc);
        dest=&pfb;
    }
    //===========计算相交===============
    SC_ARER intersection;
    if(!SC_pfb_intersection(dest,&intersection,xs,ys,xs+src->w-1,ys+src->h-1))
    {
        return;
    }
    uint16_t *Image=(uint16_t*)src->map;
    for (int y = intersection.ys; y <=intersection.ye; y++)
    {
        int dest_offs=(y-dest->ys) * dest->w -dest->xs;
        int src_offs= (y-ys) * src->w - xs;
        for (int x = intersection.xs; x <=intersection.xe; x++)
        {
            dest->buf[dest_offs+x]=Image[src_offs+x];
        }
    }
    if(pfb.buf)
    {
        if(SC_pfb_Refresh(&pfb,0))
        {
            goto __PFB_Image;
        }

    }
}


///=============================字体位图================================================
/**fun: get_bpp_value*/
static inline uint16_t get_bpp_value(const uint8_t *buffer,uint16_t offset, uint8_t bpp)
{
    uint16_t alpha=0;
    switch (bpp)
    {
    case 8:
        alpha= (buffer[offset]);
        break;
    case 4:
        alpha= (buffer[offset / 2] >> (4 * (1 - (offset % 2)))) & 0x0F;
        alpha= alpha*17;
        break;
    case 2:
        alpha= (buffer[offset / 4] >> (2 * (3 - (offset % 4)))) & 0x03;
        alpha= alpha*85;
        break;
    case 1:
        alpha= (buffer[offset / 8] >> (7 - (offset % 8))) & 0x01 ? 255 : 0;
        break;
    default:
        break;
    }
    return  alpha;
}

///显示一个C51字符
int SC_pfb_C51_letter(SC_tile *dest,int xs,int ys,uint16_t w,uint16_t h,const uint8_t *src,uint16_t fc,uint16_t bc)
{
    uint16_t alpha;
    int y1= SC_MAX(ys,dest->ys);            //ys边界限定
    int y2= SC_MIN(ys+h,dest->ys+dest->h);  //ye边界限定
    if(y1>=y2) return 0;
    int x1= SC_MAX(xs,dest->xs);            //xs边界限定
    int x2= SC_MIN(xs+w,dest->xs+dest->w);  //xe边界限定
    if(x1>=x2) return 0;
    for (int x = x1; x <x2; x++)
    {
        int dest_offs=(y1-dest->ys) * dest->w+x-dest->xs;
        int src_x = x - xs;
        for (int y = y1; y <y2; y++,dest_offs+=dest->w)
        {
            int src_y = y- (ys);
            alpha=get_bpp_value(src,src_y * w+src_x, 1);
            set_pixel_value(dest,dest_offs,alpha,fc);
        }
    }
    return 1;
}


///====================== LVGL字体=====================================
//将utf-8编码转为unicode编码（函数来自LVGL）
uint32_t lv_txt_utf8_next(const char * txt, uint32_t * i)
{
    uint32_t result = 0;
    uint32_t i_tmp = 0;
    if(i == NULL) i = &i_tmp;
    if((txt[*i] & 0x80) == 0)     //Normal ASCII
    {
        result = txt[*i];
        (*i)++;
    }
    else    //Real UTF-8 decode
    {
        // bytes UTF-8 code
        if((txt[*i] & 0xE0) == 0xC0)
        {
            result = (uint32_t)(txt[*i] & 0x1F) << 6;
            (*i)++;
            if((txt[*i] & 0xC0) != 0x80) return 0; //Invalid UTF-8 code
            result += (txt[*i] & 0x3F);
            (*i)++;
        }
        //3 bytes UTF-8 code
        else if((txt[*i] & 0xF0) == 0xE0)
        {
            result = (uint32_t)(txt[*i] & 0x0F) << 12;
            (*i)++;

            if((txt[*i] & 0xC0) != 0x80) return 0;
            result += (uint32_t)(txt[*i] & 0x3F) << 6;
            (*i)++;

            if((txt[*i] & 0xC0) != 0x80) return 0;
            result += (txt[*i] & 0x3F);
            (*i)++;
        }
        else if((txt[*i] & 0xF8) == 0xF0)
        {
            result = (uint32_t)(txt[*i] & 0x07) << 18;
            (*i)++;
            if((txt[*i] & 0xC0) != 0x80) return 0;
            result += (uint32_t)(txt[*i] & 0x3F) << 12;
            (*i)++;

            if((txt[*i] & 0xC0) != 0x80) return 0;
            result += (uint32_t)(txt[*i] & 0x3F) << 6;
            (*i)++;

            if((txt[*i] & 0xC0) != 0x80) return 0;
            result += txt[*i] & 0x3F;
            (*i)++;
        }
        else
        {
            (*i)++;
        }
    }
    return result;
}

//显示一个lvgl字符
void SC_pfb_lv_letter(SC_tile *dest,SC_ARER *align,int xs,int ys,lv_font_glyph_dsc_t *dsc,uint32_t unicode, lv_font_t *font,uint16_t fc,uint16_t bc)
{
    uint16_t w= dsc->adv_w;
    uint16_t h= font->line_height;
    int xe=xs+w-1;
    int ye=ys+h-1;
    int offs_y= ys+(h-dsc->box_h-dsc->ofs_y-font->base_line);  //
    int offs_x= xs+dsc->ofs_x;
    //-----------对齐窗口-------------------------
    ys= SC_MAX(ys,  align->ys);  //ys边界限定
    ye= SC_MIN(ye,  align->ye);  //ye边界限定
    if(ys>=ye) return ;
    xs= SC_MAX(xs, align->xs);    //xs边界限定
    xe= SC_MIN(xe, align->xe);    //xe边界限定
    if(xs>=xe) return ;
    SC_tile pfb= {0};

__PFB_lv_letter:
    if(dest==NULL||pfb.buf)
    {
        //创建局部pfb
        SC_pfb_clip(&pfb,xs,ys,xe,ye,gui->bkc);
        dest=&pfb;
    }
    //-----------计算相交-------------------------
    SC_ARER intersection;
    if(!SC_pfb_intersection(dest,&intersection,xs,ys,xe,ye))
    {
        return;
    }
    int x,y,src_x,src_y;
    uint16_t alpha;
    const uint8_t *src =font->get_glyph_bitmap(font,unicode);
    for ( y = intersection.ys; y <=intersection.ye; y++)
    {
        int dest_offs=(y-dest->ys) * dest->w -dest->xs;
        src_y = y- offs_y;
        for ( x = intersection.xs; x <=intersection.xe; x++)
        {
            src_x = x - offs_x;
            if(bc!=gui->bkc)
            {
                set_pixel_value(dest,dest_offs+x,gui->alpha,bc);
            }
            if (src_x < 0 || src_x >= dsc->box_w||src_y < 0 || src_y >= dsc->box_h)
            {
                continue;
            }
            else
            {
                alpha=get_bpp_value(src,src_y * dsc->box_w+src_x, dsc->bpp);
                set_pixel_value(dest,dest_offs+x,alpha,fc);
            }
        }
    }
    if(pfb.buf)
    {
        if(SC_pfb_Refresh(&pfb,0))
        {
            goto __PFB_lv_letter;
        }
    }
}


//设置字体间距
void SC_set_font_x_scale(lv_font_t* font,uint16_t Xscale)
{
    lv_font_fmt_txt_dsc_t *dsc=font->dsc;
    dsc->kern_scale=Xscale;
}

//计算长度+间距
static bool lv_get_glyph_dsc(lv_font_t *font, lv_font_glyph_dsc_t *glyph, uint32_t unicode,int *len)
{
    lv_font_fmt_txt_dsc_t *dsc=font->dsc;
    if( font->get_glyph_dsc(font,glyph,unicode,0))
    {
        glyph->adv_w+=dsc->kern_scale;
        *len+=glyph->adv_w;
        return 1;
    }
    return 0;
}
//长文本显示自动换行，支持\n换行，返回0未结束，返回1结束.
int SC_pfb_printf(SC_tile *dest, int x,int y,const char* txt,uint16_t fc,uint16_t bc, lv_font_t* font)
{
    lv_font_glyph_dsc_t g;
    uint32_t i =0;
    uint32_t unicode;
    SC_ARER *box=&gui->lcd_area;
    if(dest)
    {
        //===========计算相交===============
        SC_ARER intersection;
        if(!SC_pfb_intersection(dest,&intersection,box->xs,box->ys,box->xe,box->ye))
        {
            return 0;
        }
    }
    int xlen=0;
    for(;; x+=g.adv_w)
    {
        unicode = lv_txt_utf8_next(txt,&i);      //txt转unicode
        if(lv_get_glyph_dsc(font,&g,unicode,&xlen)==0) //长度累加直到结束
        {
            if(unicode==0)                      //结束符
            {
                return 1;
            }
            else if(unicode=='\n'||unicode=='\r')
            {
                x=box->xe;
                continue;
            }
            else
            {
                unicode=' ';               //未知字体
                lv_get_glyph_dsc(font,&g,unicode,&xlen);
            }
        }
        if(x+g.adv_w>=box->xe)        //换行
        {
            x=box->xs;
            y+=font->line_height;
            if(y>box->ye)  break;
        }
        SC_pfb_lv_letter(dest,box,x,y,&g,unicode,font,fc,bc);
    }
    return 0;
}


///===================label控件===================================
///设置label参数
void SC_set_label(SC_label *label,int xs,int ys,int w,int h,const char *str,LABEL_ALIGN align)
{
    label->box.xs=xs;
    label->box.ys=ys;
    label->box.xe=xs+w-1;
    label->box.ye=ys+h-1;
    label->align = align;  // |STR_SHOW_BORDER2
    label->str=str;
}
///设置label边框
static void SC_set_label_border(SC_tile *dest,SC_label *label)
{
    SC_ARER* box=&label->box;
    if(label->align&STR_SHOW_BORDER)       //简单边框
    {
        SC_pfb_DrawFrame(dest,box->xs, box->ys, box->xe, box->ye,C_WHITE);
    }
    else if(label->align&STR_SHOW_BORDER2) //圆角边框
    {
        SC_pfb_RoundFrame(dest, box->xs, box->ys, box->xe, box->ye, 4,3,C_WHITE,C_BLUE);
    }
}
///显示label控件
int SC_pfb_label(SC_tile *dest,SC_label *label,int xofs,int yofs,uint16_t fc,uint16_t bc,lv_font_t* font)
{
    lv_font_glyph_dsc_t g[30];          //描述符号的属性。
    uint32_t unicode[30];               //最大字符数
    SC_ARER *box= &label->box;
    SC_tile pfb= {0};
__PFB_label:
    if(dest==NULL||pfb.buf)
    {
        SC_pfb_clip(&pfb,box->xs,box->ys,box->xe,box->ye,gui->bkc); //创建局部pfb
        dest=&pfb;
    }
    //===========计算相交===============
    SC_ARER intersection;
    if(!SC_pfb_intersection(dest,&intersection,box->xs,box->ys,box->xe,box->ye))
    {
        return 0;
    }
    int x=xofs,y=yofs;
    int k,j=0,xlen=0;
	uint32_t i=0;
    for(j=0; j<30; j++)
    {
        unicode[j] =lv_txt_utf8_next(label->str,&i);                 //txt转unicode
        if(lv_get_glyph_dsc(font,&g[j],unicode[j],&xlen)==0) //长度累加直到结束
        {
            if(unicode[j])
            {
                unicode[j]=' ';                                 //未知字体替代
                lv_get_glyph_dsc(font,&g[j],unicode[j],&xlen);
                continue;
            }
            break;
        }
    }
    //-------------------对齐偏移计算-----------------------
    switch (label->align&0x03)
    {
    case STR_ALIGN_CENTER:        //居中对齐
    case STR_ALIGN_RIGHT:         //右对齐
        k=(box->xe- xlen);        //右剩余
        x+= ((label->align&0x03)==STR_ALIGN_CENTER) ? (k+box->xs+1)/2:k;
        y+=box->ys;
        break;
    default :
        x+=box->xs;
        y+=box->ys;
        break;
    }
    SC_set_label_border(dest,label);    //边框绘制
    for(k=0; k<j; k++)
    {
        SC_pfb_lv_letter(dest,box,x,y,&g[k],unicode[k],font,fc,bc);
        x+=g[k].adv_w;
    }
    if(pfb.buf)
    {
        if(SC_pfb_Refresh(&pfb,0))
        {
            goto __PFB_label;
        }
    }
    return  xlen;
}

//---------------外置lvgl字体接口-------------------------------
//#include  <SDL2/SDL.h>
//int SPIFLASH_Read(uint8_t *buf,uint32_t offset,uint32_t size)
//{
//    int err;
//    SDL_RWops *fs;
//    fs = SDL_RWFromFile("SCGUI/myFont_bin12.bin", "rb");
//    if( fs  == NULL)
//    {
//        printf("open myFont_11.bin failed\n");
//        return -1;
//    }
//    err=  SDL_RWseek(fs,offset, RW_SEEK_SET);
//    err=  SDL_RWread(fs,buf, size, 1);
//    return err;
//}


///======================波形图=====================================
#define CHART_BUF_PIX     80     //采样点
int16_t chart_buf1[CHART_BUF_PIX];
//采样点移动
void SC_chart_put_dat1(int16_t dat)
{
    uint16_t i;
    for(i=1; i<CHART_BUF_PIX; i++)
    {
        chart_buf1[i-1]=chart_buf1[i];     //波形前移
    }
    chart_buf1[i-1]=dat;                  //入队列
}
//波形线性插值，采样点数放大到全屏
void SC_bilinear_bmp1(int16_t *src,int16_t *dst,uint16_t src_width, uint16_t dst_width)
{
    uint32_t j,x,x_ratio;
    int32_t  x_diff, x_diff_comp;           //权重

    for ( j = 0; j < dst_width; j++)
    {
        x_ratio = (j<<8)*(src_width-1)/(dst_width-1);             //缩放系数,防止边界问题指针超出
        x =  x_ratio >> 8;                                        //坐标取整
        x_diff = x_ratio - (x << 8);                              //坐标取余
        x_diff_comp = (1 << 8) - x_diff;                          //1-余
        //-----------邻值取权重--------------
        int32_t result = (x_diff_comp*src[x])+(x_diff*src[x+1]);   //x,y;
        dst[j]=result/256;
    }
}


int16_t out_buf[200];
void  SC_pfb_chart(SC_tile *dest,SC_tile* chart,int xd,int yd,int16_t vol,uint16_t fc,uint16_t gc)
{
    int x,y;
    int xe=chart->xs+chart->w-1;
    int ye=chart->ys+chart->h-1;
    int base_line_x=chart->w/2+chart->xs; //x基准线
    int base_line_y=chart->h/2+chart->ys; //y基准线
    xd=chart->w/xd;
    yd=chart->h/yd;
    gc=alphaBlend(gc,0,128);    //网格
    SC_tile pfb= {0};

__PFB_chart:

    if(dest==NULL||pfb.buf)
    {
        SC_pfb_clip(&pfb,chart->xs,chart->ys,xe,ye,gui->bkc); //创建局部pfb
        dest=&pfb;
    }
    if(dest->stup==0)
    {
        SC_chart_put_dat1(vol);
        SC_bilinear_bmp1(chart_buf1,out_buf,CHART_BUF_PIX,chart->w);  //对波形进行插值放大
    }
    //===========计算相交===============
    SC_ARER intersection;
    if(!SC_pfb_intersection(dest,&intersection,chart->xs,chart->ys,xe,ye))
    {
        return ;
    }
    int dest_offs;
    for(y=intersection.ys; y<=intersection.ye; y++)
    {
        if((y-base_line_y)%yd==0||(y==chart->ys||y==chart->ys+chart->h-1))
        {
            dest_offs=(y-dest->ys)*dest->w+(intersection.xs-dest->xs);
            for(x=intersection.xs; x<=intersection.xe; x++)
            {
                dest->buf[dest_offs++]=gc; //水平线
            }
        }
    }
    // xtime++;                 //时间轴
    for(x=intersection.xs; x<=intersection.xe; x++)
    {
        int xi=x-chart->xs;
        if(xi==0||xi==chart->w-1||(x-base_line_x)%xd==0)
        {
            dest_offs=(intersection.ys-dest->ys) * dest->w+x-dest->xs;
            for(y=intersection.ys; y<=intersection.ye; y++)
            {
                dest->buf[dest_offs]=gc;	//垂直线
                dest_offs+=dest->w;
            }
            if(xi==0||xi==chart->w-1)continue;
        }
        int min=base_line_y-out_buf[xi];
        int max=base_line_y-out_buf[xi-1];
        if(min>max)
        {
            min=max;
            max=base_line_y-out_buf[xi];
        }
        min=SC_MAX(min,intersection.ys);
        max=SC_MIN(max,intersection.ye);
        dest_offs=(min-dest->ys) * dest->w+x-dest->xs;
        for(y=min; y<=max; y++)
        {
            dest->buf[dest_offs]=fc;			//波形
            // set_pixel_value(dest,dest_offs,gui->alpha,fc);
            dest_offs+=dest->w;
        }
    }
    if(pfb.buf)
    {
        if(SC_pfb_Refresh(&pfb,0))
        {
            goto __PFB_chart;
        }
    }

}



